package calpi;

import java.util.LinkedList;
/**
 * Classe responsável pela descrição do objeto aluno
 * @author Sem iNick
 */
public class Aluno {

    private String nome;
    private int matricula;
    private String endereco;
    //Curso que o aluno cursa
    private Curso curso;
    private int periodo;
    /*
     * Lista encadeada para a criação das disciplinas. Não se preocupe em
     * entendê-la.
     */
    private LinkedList<Disciplina> disciplinas;

    /**
     * Cria um novo objeto Aluno com suas características e suas disciplinas
     * cursadas.
     * @param nome Nome do aluno
     * @param mat Matrícula do aluno
     * @param ender Endereço do aluno
     * @param curso Código do curso do aluno
     * @param per Período do aluno
     * @param disciplinas Disciplinas cursadas pelo aluno
     * @throws IllegalArgumentException Se matrícula menor que zero
     * @throws IllegalArgumentException Se período menor que um
     * @throws NullPointerException Se ender for nulo
     * @throws NullPointerException Se nome for nulo
     */
    public Aluno(String nome, int mat, String ender, Curso curso, int per,
                    Disciplina[] disciplinas) {

        setNome(nome);
        setMatricula(mat);
        setEndereco(ender);
        setCurso(curso);
        setPeriodo(per);
        setDisciplinas(disciplinas);
    }

    /**
     * Cria um objeto aluno com sua caracteríticas e com uma lista vazia de
     * disciplinas cursadas
     * @param nome Nome do aluno
     * @param mat Matrícula do aluno
     * @param ender Endereço do aluno
     * @param curso Código do curso do aluno
     * @param per Período do aluno
     * @throws IllegalArgumentException Se matrícula menor que zero
     * @throws IllegalArgumentException Se período menor que um
     * @throws NullPointerException Se ender for nulo
     * @throws NullPointerException Se nome for nulo
     */
    public Aluno(String nome, int mat, String ender, Curso curso, int per) {

        this(nome, mat, ender, curso, per, null);
    }

    /**
     * Getter de curso
     * @return Código do curso que o aluno cursa
     */
    public Curso getCurso() {

        return curso;
    }

    /**
     * Setter para o curso do aluno
     * @param curso Novo curso do aluno
     * @throws NullPointerException Se o curso for nulo
     */
    public void setCurso(Curso curso) {

        if (curso == null) {

            throw new NullPointerException("Curso do aluno nulo");
        }
        
        this.curso = curso;
    }

    public String getEndereco() {

        return endereco;
    }

    /**
     * Setter para endereço
     * @param endereco Novo endereço do aluno
     * @throws NullPointerException Se novo endereço for nulo
     */
    public void setEndereco(String endereco) {

        if (endereco == null) {

            throw new NullPointerException("Endereço não pode ser nulo.");
        }
        
        this.endereco = endereco;
    }

    public int getMatricula() {

        return matricula;
    }

    /**
     * Setter para matrícula
     * @param matricula Nova matrícula para o aluno
     * @throws IllegalArgumentException Se matricula menor que zero
     */
    public void setMatricula(int matricula) {

        if (matricula < 0) {

            throw new IllegalArgumentException("Matricula não pode ser negativa.");
        }
        this.matricula = matricula;
    }

    public String getNome() {
        return nome;
    }

    /**
     * Setter para nome do aluno
     * @param nome Novo nome do aluno
     * @throws NullPointerException Se nome do aluno for nulo
     */
    public void setNome(String nome) {

        if (nome == null) {

            throw new NullPointerException("Nome não pode ser nulo.");
        }
        
        this.nome = nome;
    }

    public int getPeriodo() {

        return periodo;
    }

    /**
     * Setter para período do aluno
     * @param periodo Novo período do aluno
     * @throws IllegalArgumentException Se novo período for menor que um
     */
    public void setPeriodo(int periodo) {

        if (periodo < 1) {

            throw new IllegalArgumentException("Período deve ser maior que 0");
        }
        this.periodo = periodo;
    }

    /**
     * Setter para disciplinas. Ao setar novas disciplinas, as anteriores serão
     * apagadas. Passando <i>null</i>, as disciplinas estarão sendo apagadas.
     * Se você quer somete adicionar novas disciplinas veja o método addDiciplinas
     * @param disci Novas disciplinas
     * @see Aluno#addDisciplinas(calpi.Disciplina[])
     */
    public void setDisciplinas(Disciplina[] disci) {

        disciplinas = new LinkedList<Disciplina>();

        if (disci != null) {
            
            for (Disciplina d : disci) {

                disciplinas.add(d);
            }
        }
    }

    /**
     * Getter para disciplinas
     * @return Um array contendo as disciplinas cursadas pelo aluno
     */
    public Disciplina[] getDisciplinas() {

        Disciplina[] d = new Disciplina[disciplinas.size()];
        disciplinas.toArray(d);
        return d;
    }

    /**
     * Verifica se dada disciplinas foi cursada pelo aluno
     * @return true se foi cursada ou falso caso não
     */
    public boolean cursada(Disciplina d) {

        return disciplinas.contains(d);
    }

    /**
     * Adiciona uma nova disciplina às disciplinas cursadadas pelo aluno
     * @param disc Nova disciplina cursada
     * @see Aluno#addDisciplinas(calpi.Disciplina[])
     */
    public void addDisciplina(Disciplina disc) {

        disciplinas.add(disc);
    }

    /**
     * Adiciona uma série de disciplinas às disciplinas cursadas.
     * @param discs Novas disciplicas que serão adicionadas
     * @throws NullPointerException Se for passada uma array nula
     * @see Aluno#setDisciplinas(calpi.Disciplina[])
     */
    public void addDisciplinas(Disciplina[] discs) {

        for (Disciplina d : discs) {

            addDisciplina(d);
        }
    }

    /**
     * Remove uma certa disciplina nas disciplinas cursadas pelo aluno
     * @param d Disciplina a ser removida
     * @return True se a disciplina existir nas disciplinas cursadas e for removida
     * ou false caso contrário
     */
    public boolean removeDisciplina(Disciplina d) {

        return disciplinas.remove(d);
    }
}
